#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <opencv4/opencv2/opencv.hpp>
#include "opencv4/opencv2/core/core.hpp"
#include <opencv4/opencv2/highgui/highgui.hpp>
#include "Serror.hpp"
#include "Sdefine.hpp"

#include<sys/socket.h>	//socket
#include<sys/types.h>
#include<netinet/in.h>

using namespace std;
using namespace cv;

#define PORT 3456    // 定义端口号为3456

#define FRAME_WIDTH         640   // 定义图像宽度为640
#define FRAME_HEIGHT        480   // 定义图像高度为480

void error(const char *msg)
{
  perror(msg);
  exit(1);
}



int main()
{
  int sockfd, newsockfd, portno, n, imgSize, bytes=0, IM_HEIGHT, IM_WIDTH;;
  socklen_t clilen;
  char buffer[256];
  struct sockaddr_in serv_addr, cli_addr;

  cv::CascadeClassifier face_cascade; 

  //确认加载了正确的人脸检测分类器  ，请确保文件路径正确，并且文件已正确加载到cv::CascadeClassifier对象中。
  if (!face_cascade.load("path_to_haarcascade_frontalface_default.xml")) {  
    std::cerr << "Error: Could not load face cascade classifier." << std::endl;  
    return -1;  
  }
  
  face_cascade.load("haarcascade_frontalface_default.xml");
  face_cascade.load("/home/lhm/opencv-4.x/data/haarcascades/haarcascade_frontalface_default.xml");
  cv::CascadeClassifier eye_cascade; eye_cascade.load("/home/lhm//opencv-4.x/data/haarcascades/haarcascade_eye.xml");
  cv::CascadeClassifier smile_cascade; smile_cascade.load("/home/lhm//opencv-4.x/data/haarcascades/haarcascade_smile.xml");
  Mat img;   // 定义图像对象

  sockfd=socket(AF_INET, SOCK_STREAM, 0);
  if(sockfd<0) error("ERROR opening socket");

  bzero((char*)&serv_addr, sizeof(serv_addr));
  portno = PORT;

  serv_addr.sin_family=AF_INET;
  serv_addr.sin_addr.s_addr=INADDR_ANY;
  serv_addr.sin_port=htons(portno);

  if(bind(sockfd, (struct sockaddr *) &serv_addr,
  sizeof(serv_addr))<0) error("ERROR on binding");

  listen(sockfd,5);
  clilen=sizeof(cli_addr);

  newsockfd=accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); //通过accept函数给描述符赋值
  if(newsockfd<0) error("ERROR on accept");


  bool running = true;

  while(running)
  {
    IM_HEIGHT = FRAME_HEIGHT;
    IM_WIDTH = FRAME_WIDTH;
    img = Mat::zeros(FRAME_HEIGHT, FRAME_WIDTH, CV_8UC3);  // 创建一个图像对象，尺寸为FRAME_HEIGHT x FRAME_WIDTH，数据类型为CV_8UC3

    imgSize = img.total()*img.elemSize();   // 计算图像数据的大小，即像素总数乘以每个像素的字节数
    uchar sockData[imgSize];   // 创建一个长度为imgSize的uchar数组，用于存储接收到的图像数据

    for(int i=0;i<imgSize;i+=bytes)   // 循环接收图像数据
      if ((bytes=recv(newsockfd, sockData+i, imgSize-i,0))==-1) error("recv failed");

    int ptr=0;

    for(int i=0;i<img.rows;++i)   // 将接收到的图像数据复制到img中
      for(int j=0;j<img.cols;++j)
      {
        //从sockData数组中取出三个连续的元素，并将它们转化为Vec3b类型，然后赋值给img的第(i, j)位置的像素值。
        img.at<Vec3b>(i,j) = Vec3b(sockData[ptr+0],sockData[ptr+1],sockData[ptr+2]);
        ptr=ptr+3;
      }

    //将图像转换为灰度图
    cv::Mat grayFrame;
    cv::Mat img = cv::imread("path_to_your_image.jpg"); 
    imshow("图片显示", img);
	  waitKey(0);
    if (img.empty()) 
    { 
      std::cerr << "图像加载失败，请检查文件路径！" << std::endl;
     // 可以选择退出程序或进行其他错误处理 return -1; 
     }
    cv::cvtColor(img, grayFrame, cv::COLOR_BGR2GRAY);

   // 进行人脸检测
    std::vector<cv::Rect> faces;
    face_cascade.detectMultiScale(grayFrame, faces, 1.1, 6, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

   // 对每个检测到的人脸进行处理
    int faceCount = 0;
    for (const auto& face : faces)
       {
        cv::rectangle(img, face, cv::Scalar(0, 255, 0), 2);
        cv::putText(img, "Face", cv::Point(face.x, face.y - 10), cv::FONT_HERSHEY_SIMPLEX, 0.9, cv::Scalar(0, 255, 0), 2);

        faceCount++;  
        // 在人脸区域进行眼睛检测
        cv::Mat faceROI = grayFrame(face);
        std::vector<cv::Rect> eyes;
        eye_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

        // 绘制眼睛标识
        int eyeCount = 0;
        for (const auto& eye : eyes)
         {
                cv::Point eyeCenter(face.x + eye.x + eye.width / 2, face.y + eye.y + eye.height / 2);
                int radius = cvRound((eye.width + eye.height) * 0.25);
                cv::circle(img, eyeCenter, radius, cv::Scalar(255, 0, 0), 2);
                eyeCount++;
         }

        // 在人脸区域进行嘴巴检测
        std::vector<cv::Rect> smiles;
        smile_cascade.detectMultiScale(faceROI, smiles, 1.3, 5, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

        // 绘制嘴巴标识
        int smilesCount = 0;
        for (const auto& smile : smiles)
            {
                cv::rectangle(img, cv::Point(face.x + smile.x, face.y + smile.y),
                    cv::Point(face.x + smile.x + smile.width, face.y + smile.y + smile.height),
                    cv::Scalar(0, 0, 255), 2);
                cv::putText(img, "Smile", cv::Point(face.x + smile.x, face.y + smile.y - 10), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 2);

                smilesCount++;
            }
        
        std::cout << "Detected " << faceCount << " faces, " << eyeCount << " eyes, and" << smilesCount << "simles."<< std::endl; 
        }

        
    namedWindow( "Server", CV_MINOR_VERSION);// 创建一个窗口用于显示图像
    imshow( "Server", img);   // 在窗口中显示图像
    char key = waitKey(5);   // 等待用户按键操作，等待时间为5ms
    //esc
    if(key==27) running =false;   // 如果用户按下ESC键，跳出循环，退出程序
  }

  close(newsockfd);   // 关闭客户端套接字
  close(sockfd);   // 关闭服务器套接字

  return 0;
}